package com.five.matebook.activity.columeedit;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.Nullable;

import com.five.matebook.R;

import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;

public class EditItemView extends LinearLayout {
    private static final String TAG = EditItemView.class.getSimpleName();
    private LinearLayout mLinearItem;
    private EditText mEditItem;
    private TextView mTxtItem;
    private LinearLayout mSubContainer;
    private ImageView mImageDel;

    private boolean mRoot = true;

    @SuppressLint("MissingInflatedId")
    private void inflate(Context context) {
        View child = LayoutInflater.from(context).inflate(R.layout.cumstom_edit_item, null);
        mLinearItem = child.findViewById(R.id.linear_item);
        mEditItem = child.findViewById(R.id.edit_item);
        mTxtItem = child.findViewById(R.id.txt_item);
        mImageDel = child.findViewById(R.id.img_del);
        mSubContainer = child.findViewById(R.id.linear_sub_item_container);
        this.addView(child);

        if (!mIsExtraItem) {
            mEditItem.setOnFocusChangeListener(new OnFocusChangeListener() {
                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    if (hasFocus) {
                        mEditItem.setSelection(mEditItem.getText().length());
                        InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                        imm.showSoftInput(mEditItem, InputMethodManager.SHOW_IMPLICIT);
                    } else {
                        if (!mRoot) {
                            doModify();
                        }
                    }
                    Log.d("editItemView", "on edittext fouces changed:" + hasFocus);
                }
            });
            mEditItem.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    if (!TextUtils.isEmpty(defaultValue) && !defaultValue.contentEquals(s)) {
                        mEditItem.setTextColor(Color.GREEN);
                    } else {
                        mEditItem.setTextColor(getResources().getColor(R.color.txt_normal_color));
                    }
//                    mTxtItem.setText(s);
                }

                @Override
                public void afterTextChanged(Editable s) {

                }
            });
            InputFilter[] filters = new InputFilter[1];
            filters[0] = new InputFilter.LengthFilter(7);
            mEditItem.setFilters(filters);

            mTxtItem.setOnLongClickListener(new OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    mTxtItem.setVisibility(View.GONE);
                    mEditItem.setVisibility(View.VISIBLE);
                    mEditItem.requestFocus();
                    return true;
                }
            });
            mTxtItem.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    toggleExpand();
                }
            });

            {
                mImageDel.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        EditItemView parent = getParentEditItemView();
                        parent.doDel(EditItemView.this);
                    }
                });
            }
        } else {
            // add item
            mImageDel.setVisibility(GONE);
            mTxtItem.setGravity(Gravity.CENTER);
            mTxtItem.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    // 找到 上级 EditItemView
                    EditItemView parent = getParentEditItemView();
                    if (parent != null) {
                        parent.doAdd();
                    }
                }
            });
        }

        setValue(null);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (mRoot) {
            ViewGroup viewGroup = (ViewGroup) getParent();
            viewGroup.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    clearAllFocus();
                }
            });
        }
    }

    private void clearAllFocus() {
        if (!mRoot) {
            if (mEditItem.hasFocus()) {
                mEditItem.clearFocus();
                InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(mEditItem.getWindowToken(), 0);
                return;
            }
        }

        for (EditItemView v : subList) {
            v.clearAllFocus();
        }
    }

    public void toggleExpand() {
        if (mRoot) {
            for (EditItemView v : subList) {
                v.toggleExpand();
            }
        } else {
            if (subList.size() > 0) {
                if (mSubContainer.getVisibility() == VISIBLE) {
                    mSubContainer.setVisibility(GONE);
                } else {
                    mSubContainer.setVisibility(VISIBLE);
                }
            }
        }
    }

    private String checkEditViewValue() {
        if (TextUtils.isEmpty(mTxtItem.getText())) {
            return "item不能为空";
        } else {
            String editValue = mTxtItem.getText().toString().trim();
            if (editValue.contains(" ")) {
                return "item不能包含空格";
            }
        }
        return null;
    }

    private boolean mIsExtraItem;
    public EditItemView(Context context) {
        this(context, false);
    }

    public EditItemView(Context context, boolean isExtraItem) {
        super(context);
        mIsExtraItem = isExtraItem;
        inflate(context);
    }

    public EditItemView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        inflate(context);
        mIsExtraItem = false;
    }

    private EditItemView mAddView;
    private List<EditItemView> subList = new ArrayList<>();
    public synchronized EditItemView addOneSub(String item) {
        return addOneSub(item, -1);
    }
    public synchronized EditItemView addOneSub(String item, int index) {
        if (mAddView == null) {
            mAddView = new EditItemView(getContext(), true);
            mAddView.setValue("+");
            mAddView.mRoot = false;
            this.mSubContainer.addView(mAddView);
        }
        EditItemView sub = new EditItemView(getContext());
        sub.setValue(item);
        sub.mRoot = false;
        if (index >= 0) {
            subList.add(index, sub);
            this.mSubContainer.addView(sub, index);
        } else {
            subList.add(sub);
            this.mSubContainer.addView(sub, mSubContainer.getChildCount() -1);
        }
        return sub;
    }

    private String defaultValue;
    private void setValue(String v) {
        defaultValue = v;
        if (v == null) {
            this.mLinearItem.setVisibility(GONE);
        } else {
            this.mEditItem.setText(v);
            this.mTxtItem.setText(v);
            this.mLinearItem.setVisibility(VISIBLE);
        }
    }

    private String getValue() {
        CharSequence sequence = this.mTxtItem.getText();
        return sequence != null ? sequence.toString().trim() : "";
    }

    private int removeSubEditItemView(EditItemView sub) {
        int index = subList.indexOf(sub);
        if (index >= 0) {
            sub.setEnabled(false);
            subList.remove(sub);
            mSubContainer.removeView(sub);
        }
        return index;
    }

    private EditItemView getParentEditItemView() {
        ViewParent p = getParent();
        while (p != null) {
            if (p instanceof EditItemView) {
                return (EditItemView) p;
            }
            p = p.getParent();
        }
        return null;
    }

    public String checkItemValue() {
        if (!mRoot) {
            String tips = checkEditViewValue();
            if (!TextUtils.isEmpty(tips)) {
                return tips;
            }
        } else {
            if (this.get().size() == 0) {
                return "item个数不能为0";
            }
        }
        for (EditItemView v : subList) {
            String s = v.checkItemValue();
            if (!TextUtils.isEmpty(s)) {
                return s;
            }
        }
        return null;
    }

    public List<String> get() {
        List<String> ret = null;
        if (mRoot) {
            ret = new ArrayList<>();
            for (EditItemView v : subList) {
                ret.add(v.getString());
            }
        }
        return ret;
    }

    private String getString() {
        StringJoiner sb = new StringJoiner(" ");
        sb.add(mEditItem.getText().toString());
        for (EditItemView v : subList) {
            sb.add(v.getString());
        }
        return sb.toString();
    }

    private synchronized void doAdd() {
        EditItemView sub = this.addOneSub("");
        // 如果新增的 item下面，还有分类，那么则需要为这个item下面添加 "add item"
        boolean showAddItem = false;
        for (EditItemView item : subList) {
            if (item.subList.size() != 0) {
                showAddItem = true;
                break;
            }
        }
        if (showAddItem) {
            sub.addOneSub("item0");
        }

        sub.mTxtItem.performLongClick();
        if (mCallback != null) {
            mCallback.onOperate(IOperateCallback.ADD, new Runnable() {
                @Override
                public void run() {
                    EditItemView.this.removeSubEditItemView(sub);
                }
            });
        }
    }

    private synchronized void doDel(EditItemView sub) {
        int index = this.removeSubEditItemView(sub);
        if (mCallback != null && index >= 0) {
            mCallback.onOperate(IOperateCallback.DEL, new Runnable() {
                @Override
                public void run() {
//                    addOneSub(sub.getValue(), index);
                    sub.setEnabled(true);
                    subList.add(index, sub);
                    mSubContainer.addView(sub, index);
                }
            });
        }
    }

    private synchronized void doModify() {
        String tips = checkEditViewValue();
        if (!TextUtils.isEmpty(tips)) {
//            Toast.makeText(getContext(), tips, Toast.LENGTH_SHORT).show();
        }

        final String oldValue = getValue();

        if (oldValue.contentEquals(mEditItem.getText())) {
            // value don't change. do nothing
            return;
        }

        mEditItem.setVisibility(GONE);
        mTxtItem.setVisibility(VISIBLE);
        mTxtItem.setText(mEditItem.getText());

        if (!mRoot) {
            if (TextUtils.isEmpty(defaultValue) || !defaultValue.contentEquals(mTxtItem.getText())) {
                mTxtItem.setTextColor(Color.GREEN);
            } else {
                mTxtItem.setTextColor(getResources().getColor(R.color.txt_normal_color));
            }
        }

        if (TextUtils.isEmpty(defaultValue) && "".contentEquals(mTxtItem.getText())) {
            return;
        }

        if (!isEnabled()) {
            return;
        }

        if (mCallback != null) {
            mCallback.onOperate(IOperateCallback.MOD, new Runnable() {
                @Override
                public void run() {
                    mTxtItem.setText(oldValue);
                    mEditItem.setText(oldValue);
                }
            });
        }
    }

    private static IOperateCallback mCallback;
    public synchronized void setOperateCallback(IOperateCallback callback) {
        mCallback = callback;
    }

    interface IOperateCallback {
        int ADD = 0;
        int DEL = 1;
        int MOD = 2;
        void onOperate(int opt, Runnable onRestoreRunnable);
    }
}
